<?php
require_once dirname(__FILE__) . '/libraries/ServiceBase.php';
/**
 * SDO OA库 查询 对外接口调用封装
 * 
 * @category SDO
 * @package OPEN
 * @author <xucongbin@snda.com> 
 * @copyright SDO OP
 * @license http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @link http://www.sdo.com/
 * @since File available since Release 1.0.0
 */
class OAApi extends ServiceBase
{
    /**
     * restful接口
     */
    CONST REST_URL = "OAAPI_REST";
    /**
     * 测试restful接口
     */
    CONST PRE_REST_URL = "OAAPI_REST";
    /**
     * 授权信息，写死，格式：1.1.1,1.1.2,1.1.7,1.1.8,3.1.1
     */
    CONST AUTH_INFO_DEFAULT = '1.1.1';
    /**
     * IP端口，默认不填
     */
    CONST CLIENT_PORT_DEFAULT = "-1";
    /**
     * 审批状态
     */
    CONST AUDIT_FLAG = 3;
    /**
     * 用户账户类型，前台统一为数字账号
     */
    CONST USER_ID_TYPE = 2;
    /**
     * 原来的编码格式
     */
    CONST IN_CHARSET = "UTF-8";
    /**
     * 转码后的编码格式
     */
    CONST OUT_CHARSET = "GBK";
    /*
	 * 默认环境：正式环境
	 */
    CONST ENV_DEFAULT = 2;
    /**
     * 环境列表 1：联调环境，2：正式环境
     */
    protected static $ENVList = array(
        1 => "testenv", 
        2 => "onlineenv"
    );
    /**
     * 操作列表，1：添加，2：修改，3：删除
     */
    protected static $OPList = array(
        "add" => 1, 
        "update" => 2, 
        "delete" => 3
    );
    /**
     * 扣费成功失败状态，成功的订单or失败的订单(
     */
    protected static $SUCCType = array(
        1 => "yes", 
        0 => "no"
    );
    /**
     * 用户id类型, passport 通行证 number 数字帐号
     */
    protected static $UIDType = array(
        1 => "passport", 
        2 => "number"
    );
    CONST QUERY_SUCCESS = 10003;
    CONST QUERY_TOO_MANY = 20000;
    protected static $MsgList = array(
        // error
        "-10000" => "The operation is not supported by us.", 
        "-10001" => "The given parameter is invalide.", 
        "-10002" => "We met an exception when processing the request.", 
        "-10003" => "We already have a qftcfg record which has the given appid, areaid and groupid.", 
        "-10004" => "We already have a service with the given service id.",
        // success
        "10000" => "We have done the update operation successfully.", 
        "10001" => "We have done the add operation successfully.", 
        "10002" => "We have done the delete operation successfully.", 
        "10003" => "We have done the load operation successfully.", 
        // warn
        "20000" => "Too many records for your input filters."
    );
    /**
     * 产品操作
     * 
     * @param mixed $message 错误信息
     * @param array $params 参数array("appId"=>统一编码库的游戏id 数据类型 long,
     * "typeId"=>扣帐类型 (0 扣用户该应用对应帐户 1 扣用户总帐),
     * "appName"=>应用名字,
     * "spId"=>服务提供商id,
     * "timeTypeId"=>消费模式 (消费模式，时长消费为1，pt点消费为2，OA转账为4，OA道具计费为5),
     * "createUser"=>游戏创建者,
     * "manageId"=>游戏类型 (1客户端游戏 2网站/网页游戏 3产品应用),
     * "auditFlag"=>审批状态(1未审批 2待审核 3审批通过 4审批不通过),
     * "note"=>备注,
     * "signarith"=>加密方式 1：MD5，2:RSA,
     * "currencyList"=>array(货币类型列表,
     * array(,
     * "currencyName"=>货币名,
     * "currencyRate"=>人民币与货币的比值（1RMB:n游戏币）,
     * ),
     * array(,
     * "currencyName"=>货币名,
     * "currencyRate"=>人民币与货币的比值（1RMB:n游戏币）,
     * ))
     * )
     * @param string $op 操作 （暂时没有删除操作）
     * @param int $env 环境
     * @return boolean 
     */
    public static function app (&$message, $params, $op, $env = 1)
    {
        if (! isset(self::$OPList[$op]) || ! isset($params['appId']) || ! isset($params['spId'])) {
            $message ="Invalid Parameter";
            return false;
        }
        if (! isset(self::$ENVList[$env])) {
            $env = self::ENV_DEFAULT;
        }
        $need = array(
            "appName", 
            "timeTypeId", 
            "createUser", 
            "manageId", 
            "auditFlag", 
            "note", 
            "signarith", 
            //"currencyList"
        );
        if ($op != "delete" && ! self::_validateParam($params, $need, $message)) {
            return false;
        }
        $param = array(
            'operation' => $op . "App", 
            'env' => self::$ENVList[$env], 
            'app' => $params
        );
        $result = self::send($message, null, $param);
        if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->resultCode < 10000 || $result->resultCode > 10003 ) {
                // self :: log( "errCode:{$result -> resultCode} errMsg:{$result -> resultMessage}", "OAApi_app" );
            $message = $result->resultMessage;
            if ($result->resultCode == - 10004) {
                return true;
            }
            self::log(
            "method: " . __FUNCTION__ . "\tparams: " . json_encode($param) . "\tenv: {$env}\treturn: " .
             json_encode($result), __CLASS__);
            return false;
        }
        self::log(
        "method: " . __FUNCTION__ . "\tparams: " . json_encode($param) . "\tenv: {$env}\treturn: " . json_encode(
        $result), __CLASS__, true);
        return true;
    }
    /**
     * 区操作
     * 
     * @param array $message 错误信息
     * @param array $params 参数array("areaId"=>统一编码库的区id 数据类型 long,
     * "appId"=>所属应用ID,
     * "auditFlag"=>审批状态，三期如果正式环境修改区组无需审批，就一直填3,
     * "createUser"=>区创建者,
     * "name"=>区名,
     * "status"=>有效1 无效2,)
     * @param string $op 操作
     * @param int $env 环境
     * @return boolean 
     */
    public static function area (&$message, $params, $op, $env = 1)
    {
        if (! isset(self::$OPList[$op]) || ! isset($params['appId']) || ! isset($params['areaId'])) {
//            self :: log( "Invalid Parameter", "OAApi_area" );
            $message ="Invalid Parameter";
            return false;
        }
        if (! isset(self::$ENVList[$env])) {
            $env = self::ENV_DEFAULT;
        }
        if ($op != 'delete') {
            $need = array(
                'status', 
                'createUser'
            );
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
            if (! isset($params['auditFlag'])) {
                $params['auditFlag'] = self::AUDIT_FLAG;
            }
            $params['note'] = "";
        }
        $param = array(
            'operation' => $op . "Area", 
            'env' => self::$ENVList[$env], 
            'area' => $params
        );
        $result = self::send($message, null, $param);
        if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->resultCode < 10000 || $result->resultCode > 10003 ) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message =$result->resultMessage;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * 组操作
     * 
     * @param array $message 错误日志
     * @param array $params 参数 array(
     * "groupId"=>统一编码库的组id 数据类型 long,
     * "appId"=>所属应用ID,
     * "areaId"=>统一编码库的区id 数据类型 long,
     * "createUser"=>组创建者,
     * "name"=>组名,
     * "idc"=>IDC 1电信 2网通)
     * @param string $op 操作类型
     * @param int $env 环境
     * @return boolean 
     */
    public static function group (&$message, $params, $op, $env = 1)
    {
        if (! isset(self::$OPList[$op])) {
            $message ="Invalid Parameter";
            return false;
        }
        if (! isset(self::$ENVList[$env])) {
            $env = self::ENV_DEFAULT;
        }
        $need = array(
            'groupId', 
            'appId', 
            'areaId'
        );
        if (! self::_validateParam($params, $need, $message)) {
            return false;
        }
        $param = array(
            'operation' => $op . "Group", 
            'env' => self::$ENVList[$env], 
            'group' => $params
        );
        $result = self::send($message, null, $param);
        if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        if ($result->resultCode < 10000 || $result->resultCode > 10003 ) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
            $message =$result->resultMessage;
            return false;
        }
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
        return true;
    }
    /**
     * IP操作
     * @param string $message
     * @param array $params
     * @param string $op
     * @param int $env
     */
    public static function ip($message, $params, $op, $env = 1)
    {
        if (! isset(self::$OPList[$op]) || ! isset(self::$ENVList[$env])) {
            self::log("Invalid Parameter", "OAApi_ip");
            return FALSE;
        }        
        $need = array(
            'clientIp', 
            'alias',
            'ipid'
        );
        if (! self::_validateParam($params, $need, $message)) {
            return false;
        }
        if ($op != 'delete') {
            if (! isset($params['status'])) {
                $params['status'] = 1;
            }
            if (! isset($params['clientProtNum'])) {
                $params['clientProtNum'] = -1;
            }
            $need = array(
                'clientType', 
                'hostId'
            );
            if (! self::_validateParam($params, $need, $message)) {
                return false;
            }
        } 
        $param = array( 'operation' => $op . "Iplist", 'env' => self :: $ENVList[$env], 'iplist' => $params );
		$result = self :: send( $message, null, $param );
        if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
        
		if ($result->resultCode < 10000 || $result->resultCode > 10003 ) {
			self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
			$message =$result->resultMessage;
			return false;
		} 
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
		return true;
    }
	 
	/**
	 * 充值服务器操作
	 * 
	 * @param array $message 错误信息
	 * @param array $params 参数 array(
	 * "spId"=>服务提供商id,
	 * "groupId"=>统一编码库的组id 数据类型 long,
	 * gsipid => 生效的gameserver（OAS返回的ip_id）,
	 * "useridtype"=>用户id类型 1pt帐号 2数字帐号 3uid,
     * "qftCfgLegacyId" => 更新删除时，，提供,
	 * "ipid"=>OASPRE/OAS数据库中TB_IPList表的ip_id,
	 * "appId"=>所属应用ID,
	 * "areaId"=>统一编码库的区id 数据类型 long,
	 * "name"=>组名,
	 * "idc"=>IDC 1电信 2网通,
	 * "sendaddrtype"=>回调地址类型 1：URL;2:webservice,3socket,
	 * "sendaddr"=>回调地址,
	 * "needconfirm"=>游戏客户端在消费时是否要二次确认 1否 2是,
	 * "status"=>状态1有效 2无效,
	 * "typeid"=>与应用中的timeTypeId相同 消费模式，时长消费为1，pt点消费为2，OA转账为4，OA道具计费为5
	 * )
	 * @param string $op 操作类型
	 * @param int $env 环境
	 * @return mixed 成功返回qft_id，失败返回false  
	 */
	public static function qft ( &$message, $params, $op, $env = 1 )
	{
		if ( ! isset( self :: $OPList[$op] ) || ($op!="delete" && $params['typeid'] == 3) ) {
			$message ="Invalid Parameter";
			return false;
		} 
	    if (! isset( self :: $ENVList[$env] )) {
	    	$env = self::ENV_DEFAULT;
	    }
        if($op=="add"){
            $params['qftCfgLegacyId'] = 0;    
        }
		$need = array( 'groupId', 'appId', 'areaId', 'ipid', 'qftCfgLegacyId' );
		if ( ! self :: _validateParam( $params, $need, $message ) ) {
			return false;
		} 
		$need = array( "name", "idc", "sendaddrtype", "sendaddr", "needconfirm", "status", "typeid" );
		if ( $op!="delete" && ! self :: _validateParam( $params, $need, $message ) ) {
			return false;
		} 
		/**
		 * 添加操作时，未定义用户账号类型时，设定默认值
		 */
		if ( $op != "delete" && ! isset( $params['useridtype'] ) ) {
			$params['useridtype'] = self :: USER_ID_TYPE;
		} 
		$param = array( 'operation' => $op . "Qft", 'env' => self :: $ENVList[$env], 'qftcfg' => $params );
		$result = self :: send( $message, null, $param );
	    if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\texception: ".$message, __CLASS__);
        	return false;
        }
		if ($result->resultCode < 10000 || $result->resultCode > 10003 ) {
			self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__);
			$message =$result->resultMessage;
			return false;
		} 
        self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: {$env}\treturn: ".json_encode($result), __CLASS__, true);
		return $result ->operateObjectId;
	} 
	/**
	 * 获取对账日志
	 * 
	 * @param array $message 错误日志
	 * @param string $appId 应用ID
	 * @param string $beginDate 查询开始时间(Y-m-d)
	 * @return mixed array(
	 * array("time"=>年-月-日,
	 * "orderid"=>订单号,
	 * "app"=>App名（app id）,
	 * "area"=>区名（区id）,
	 * "group"=>组名(组id),
	 * "amount"=>金额),
	 * )
	 * @return mixed 二维数组array("time":"2008-2-20",                 --年-月-日
	 *   "orderid"=>"edf888",                 --订单号
	 *   "app"=>"功夫小子(1234)",             --App名（app id）
	 *   "area"=>"一区（231）",               --区名（区id）
	 *   "group"=>"三组(3)",                  --组名(组id)
	 *   "amount"=>5123   )
	 */
	public static function getDepositLog ( &$message, $appId, $beginDate )
	{
		if ( is_numeric( $beginDate ) ) {
			$beginDate = date( "Y-m-d", $beginDate );
		} 
		$params = array( 'appid' => $appId, 'time' => $beginDate );
		$param = array( 'operation' => 'accountCheckReport', 'filters' => $params );
		$result = self :: send( $message, null, $param );
	    if ($result===false) {
            self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: 2\texception: ".$message, __CLASS__);
        	return false;
        }
		if ( $result -> recordList||$result ->resultCode==self::QUERY_SUCCESS ) {
		    self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: 1\treturn: ".json_encode($result), __CLASS__, true);
			return ( array ) $result -> recordList;
		} else {
		    self::log("method: ".__FUNCTION__."\tparams: ".json_encode($param)."\tenv: 1\treturn: ".json_encode($result), __CLASS__);
		    $message = $result->resultMessage;
		}
		return false;
	} 
	/**
	 * 获取扣费日志
	 * 
	 * @param array $message 错误日志
	 * @param boolean $orderTrue 订单成功（1）或失败（0）
	 * @param string $beginDate 开始时间 (Y-m-d)
	 * @param string $endDate 截止时间 (Y-m-d)
	 * @param string $appId 应用ID
	 * @param string $userId 数字账号或盛大通行证
	 * @param string $userIdType 用户账号类型
	 * @param string $orderId 查询订单
	 * @return mixed array(
	 * array(
	 * "deductPaymentLog"=>(                    --扣费日志
	 * "succeed"=>成功的订单or失败的订单(yes 成功 no 失败),
	 * "orderId"=>订单号,
	 * "time"=>年-月-日 小时:分:秒,
	 * "帐号"=>用户帐号,
	 * "currencyType"=>货币类型 (仅成功订单有数据),
	 * "amount"=>额度 (仅成功订单有数据),
	 * "propInfo"=>道具信息 (仅成功订单有数据),
	 * "errorCode":"-10226115",            --错误编码 (仅失败订单有数据),
	 * "errorMessage"=>错误信息 (仅失败订单有数据),
	 * ),
	 * "propsSendingLog"=>array(                     --发货日志
	 * "orderId"=>订单号,
	 * "time"=>年-月-日 小时:分:秒,
	 * "帐号"=>用户帐号,
	 * "propInfo"=>道具信息,
	 * "status"=>道具状态,
	 * )
	 * )
	 * )
	 */
	public static function getGsOrderLog ( &$message, $orderTrue = 0, $beginDate, $endDate, $appId, $userId = null, $userIdType = null,
		$orderId = null )
	{
		if ( ! isset( self :: $SUCCType[$orderTrue] ) || ( $userId && ! isset( self :: $UIDType[$userIdType] ) ) ) {
			$message = array( "code" => - 1, "msg" => "Invalid Parameter" );
			return null;
		} 
		$params = array( 'succeed' => self :: $SUCCType[$orderTrue], 'startTime' => $beginDate, 'endTime' => $endDate,
			'appid' => $appId, 'userId' => $userId, 'userIdType' => null, 'orderId' => $orderId );
		if ( $userId ) {
			$params['userIdType'] = self :: $UIDType[$userIdType];
		} 
		if ( is_numeric( $beginDate ) ) {
			$params['startTime'] = date( "Y-m-d", $beginDate );
		} 
		if ( is_numeric( $endDate ) ) {
			$params['endTime'] = date( "Y-m-d", $endDate );
		} 
		if ( $params['endTime'] <= $params['startTime'] ) {
			$message = array( "code" => - 1, "msg" => "The end date couldn't gt begin." );
			return null;
		} 
		$param = array( 'filters' => $params, 'operation' => 'queryOrdersReport' );
		$result = self :: send( $message, null, $param );
		if ( $result ->resultCode==self::QUERY_SUCCESS ) {
			return ( array ) $result -> recordList;
		} else {
		    $message = $result->resultMessage;
		}
		return false;
	} 
	/**
	 * restful接口调用
	 * 
	 * @param array $message 错误日志
	 * @param  $apiName 方法名字
	 * @param  $apiParam 参数
	 * @param  $url string 接口地址
	 * @return mixed 
	 */
	protected static function send ( &$message, $apiName, $apiParam, $url = null )
	{
		if ( ! $url ) {
			$url = sdk_fetch_config( SDK_ENV . self :: REST_URL );
		} 
		if ( ! is_array( $apiParam ) ) {
			$apiParam = array();
		} 
		
		$tmp_param = http_build_query( array( "serviceInput" => json_encode( $apiParam ) ) ); 
		// echo $tmp_param."\n";
		//$tmp_url = $url . '?' . $tmp_param;
		if ( $apiName ) {
			// 转成按 / 分割
			$apiName = strtr( $apiName, '.', "/" );
			$url = $url . $apiName;
		} 
		$content = self :: curlPost( $url, $tmp_param, $message );
		if ($content===false) {
			return false;
		}
		$content = json_decode( $content );
		return $content;
	} 
	/**
	 * curl 方式请求
	 * 
	 * @param String $url 请求网址
	 * @param String $postString 要post的参数 格式如  xxx=1&yyy=2
	 * @param Array $option 参数 如 array(CURLOPT_REFERER=>'http://www.51.com/',CURLOPT_HTTPHEADER=>array('Host: client.sdo.com'))
	 * @return 
	 */
	private function curlPost ( $url, $postString = '', &$message )
	{
		$ch = curl_init(); // 初始化CURL句柄
		curl_setopt( $ch, CURLOPT_URL, $url ); //设置请求的URL
		curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); // 设为TRUE把curl_exec()结果转化为字串，而不是直接输出
		curl_setopt( $ch, CURLOPT_POST, 1 ); //启用POST提交
		curl_setopt( $ch, CURLOPT_POSTFIELDS, $postString ); //设置POST提交的字符串  
		curl_setopt($ch, CURLOPT_TIMEOUT, self::DEFAULT_CONNECTION_TIME_OUT);
		// curl_setopt($ch, CURLOPT_PORT, 80); //设置端口
		$timeout = 25;
		if(strstr($postString, "accountCheckReport")){
		    $timeout = 80;
		}
		curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout ); // 超时时间
		$data = curl_exec( $ch ); //执行预定义的CURL
		$info = curl_getinfo( $ch ); //得到返回信息的特性
		if ( $info['http_code'] != "200" ) {
			$message = "不能连接到服务";
			curl_close( $ch );
			return false;
		} 
		curl_close( $ch );
		return $data;
	} 
	/**
     * 自检函数
     */
    public static function selfTest() 
    {
    	$arr = array(
        	sdk_fetch_config(SDK_ENV . self::REST_URL)
    	);
    	return self::curlTest($arr);
    }
} 
